package com.hxkj.controller;

import com.alibaba.fastjson.JSON;
import com.hxkj.client.service.UserCenterServiceClient;
import com.hxkj.client.service.UserLoginHistoryServiceClient;
import com.hxkj.domain.enums.UserExceptionEnum;
import com.hxkj.domain.po.LoginToken;
import com.hxkj.domain.po.SysUser;
import com.hxkj.domain.po.Token;
import com.hxkj.domain.po.UserLoginHistory;
import com.hxkj.domain.result.UserParameterDataStruct;
import com.hxkj.service.TokenService;
import com.hxkj.utils.AES;
import com.hxkj.utils.IPUtil;
import com.platform.common.domain.exception.CustomException;
import com.platform.common.domain.exception.CustomMessageException;
import com.platform.common.domain.result.ResultDataStruct;
import com.platform.common.domain.result.ResultMessageStruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * created by kezhijie on 2018/8/30 10:25.
 * email to kezhijie@hxoss.com
 */
@RestController
@RequestMapping("user")
@Slf4j
public class UserController {

    @Autowired
    private UserCenterServiceClient userCenterServiceClient;
    @Autowired
    private UserLoginHistoryServiceClient userLoginHistoryServiceClient;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private RestTemplate restTemplate;

    private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();

    // 测试
    @GetMapping("index")
    public String index(){
        return "hello world";
    }

    // 测试
    @GetMapping("entry")
    public String entry() {
        return userCenterServiceClient.userEntry();
    }

    // 登录
    @PostMapping("login")
    public LoginToken login(@ModelAttribute SysUser sysUser, String code, HttpServletRequest request) throws Exception{

        if (StringUtils.isEmpty(sysUser.getPassword()))
            throw new CustomException(UserExceptionEnum.USER_PASSWORD_NOT_NULL);

        String encrypt = sysUser.getPassword();
        String decrypt = AES.decryptPassword(encrypt);
        sysUser.setPassword(decrypt);

        ResultDataStruct<LoginToken> resultDataStruct = userCenterServiceClient.userLogin(sysUser);

        if (resultDataStruct.getCode() == 500)
            throw new CustomMessageException(resultDataStruct.getMessage());
        if (resultDataStruct.getCode() != 200) {
            throw new CustomException(UserExceptionEnum.getEnumByCode(resultDataStruct.getCode()));
        }


        // 记录登录用户信息
        THREAD_POOL.execute(() -> buildUserLoginHistory(sysUser, request));

        return resultDataStruct.getData();
    }

    @PostMapping("registerByPhone")
    public LoginToken registerByPhone(@ModelAttribute SysUser sysUser, String code) throws Exception {
        UserParameterDataStruct<SysUser, String> userParameter = new UserParameterDataStruct<>();
        userParameter.setData(sysUser);
        userParameter.setCode(code);
        ResultDataStruct<LoginToken> resultDataStruct = userCenterServiceClient.userRegisterByPhone(userParameter);

        if (resultDataStruct.getCode() == 500)
            throw new CustomMessageException(resultDataStruct.getMessage());
        if (resultDataStruct.getCode() == 200)
            return resultDataStruct.getData();
        else
            throw new CustomException(UserExceptionEnum.getEnumByCode(resultDataStruct.getCode()));
    }

    private UserLoginHistory buildUserLoginHistory(SysUser sysUser, HttpServletRequest request) {
        UserLoginHistory loginHistory = new UserLoginHistory();
        try {
            String ip = IPUtil.getIpAddress(request);

            String physicalAddress = getPhysicalAddress(ip);


            ResultDataStruct<SysUser> resultDataStruct = userCenterServiceClient.exists(sysUser);
            SysUser existsUser = null;

            if (resultDataStruct.getCode() == 500)
                throw new CustomMessageException(resultDataStruct.getMessage());
            if (resultDataStruct.getCode() != 200) {
                throw new CustomException(UserExceptionEnum.getEnumByCode(resultDataStruct.getCode()));
            } else {
                existsUser = resultDataStruct.getData();
            }

            loginHistory.setUserId(existsUser.getUserId());
            loginHistory.setLoginName(sysUser.getUserAccount());
            loginHistory.setLoginIp(ip);
            loginHistory.setLoginLocation(physicalAddress);
            loginHistory.setLoginTime(System.currentTimeMillis());

            ResultMessageStruct resultMessageStruct =  userLoginHistoryServiceClient.record(loginHistory);

            if (resultMessageStruct.getCode() != 200)
                throw new CustomException(UserExceptionEnum.getEnumByCode(resultMessageStruct.getCode()));
        } catch (Exception e) {
            log.error("记录用户登录信息失败，userId:" + sysUser.getUserId(), e);
        }
        return loginHistory;
    }

    /**
     * 使用OkHttp访问接口拉不到数据，改用restTemplate拉数据
     * @param ip
     * @return
     */
    private String getPhysicalAddress(String ip) {
//        Map<String, Object> param = new HashMap<>();
//        param.put("ip", ip);
        try {
//            String result = HttpClient.docGet("http://ip.taobao.com/service/getIpInfo.php", param);
            String result = restTemplate.getForObject("http://ip.taobao.com/service/getIpInfo.php?ip=" + ip, String.class);
            Map<String, Object> resultInfo = JSON.parseObject(result, Map.class);
            Map<String, Object> addressInfo = JSON.parseObject(resultInfo.get("data").toString(), Map.class);
            return addressInfo.get("region").toString() + addressInfo.get("city").toString();
        } catch (Exception e) {
            return "获取物理地址失败";
        }
    }

    @PostMapping("registerByEmail")
    public void registerByEmail(@ModelAttribute SysUser sysUser, String msg) throws Exception {
        UserParameterDataStruct<SysUser, String> userStringUserParameterDataStruct = new UserParameterDataStruct<>();
        userStringUserParameterDataStruct.setCode(msg);
        userStringUserParameterDataStruct.setData(sysUser);
        ResultMessageStruct resultMessageStruct = userCenterServiceClient.userRegisterByEmail(userStringUserParameterDataStruct);

        if (resultMessageStruct.getCode() == 500)
            throw new CustomMessageException(resultMessageStruct.getMessage());
        if (resultMessageStruct.getCode() != 200)
            throw new CustomException(UserExceptionEnum.getEnumByCode(resultMessageStruct.getCode()));
    }

    @PostMapping("sendActiveEmail")
    public void sendActiveEmail(@ModelAttribute SysUser sysUser, String msg) throws Exception {
        UserParameterDataStruct<SysUser, String> userStringUserParameterDataStruct = new UserParameterDataStruct<>();
        userStringUserParameterDataStruct.setData(sysUser);
        userStringUserParameterDataStruct.setCode(msg);
        ResultMessageStruct resultMessageStruct = userCenterServiceClient.sendActiveEmail(userStringUserParameterDataStruct);

        if (resultMessageStruct.getCode() == 500)
            throw new CustomMessageException(resultMessageStruct.getMessage());
        if (resultMessageStruct.getCode() != 200)
            throw new CustomException(UserExceptionEnum.getEnumByCode(resultMessageStruct.getCode()));
    }

    @PostMapping("active")
    public void active(@ModelAttribute SysUser sysUser) throws Exception {
        ResultMessageStruct resultMessageStruct = userCenterServiceClient.active(sysUser);

        if (resultMessageStruct.getCode() == 500)
            throw new CustomMessageException(resultMessageStruct.getMessage());
        if (resultMessageStruct.getCode() != 200)
            throw new CustomException(UserExceptionEnum.getEnumByCode(resultMessageStruct.getCode()));
    }

    @PostMapping("dynamicLogin")
    public LoginToken dynamicLogin(@ModelAttribute SysUser sysUser, String code, HttpServletRequest request) throws Exception {
        UserParameterDataStruct<SysUser, String> userParameterDataStruct = new UserParameterDataStruct<>();
        userParameterDataStruct.setData(sysUser);
        userParameterDataStruct.setCode(code);

        ResultDataStruct<LoginToken> resultDataStruct = userCenterServiceClient.userDynamicLogin(userParameterDataStruct);

        if (resultDataStruct.getCode() == 500)
            throw new CustomMessageException(resultDataStruct.getMessage());
        if (resultDataStruct.getCode() != 200)
            throw new CustomException(UserExceptionEnum.getEnumByCode(resultDataStruct.getCode()));

        // 用户记录登录信息
        sysUser.setUserAccount(sysUser.getPhone());
        // 记录登录用户信息
        THREAD_POOL.execute(() -> buildUserLoginHistory(sysUser, request));

        return resultDataStruct.getData();
    }

    @GetMapping("logout")
    public void logout() throws Exception{
        ServletRequestAttributes servletRequestAttributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String accesstoken = request.getHeader("accessToken");
        if (StringUtils.isEmpty(accesstoken)) {
            // 若header中没有,则从参数中获取
            accesstoken = request.getParameter("accessToken");
        }

        if (org.springframework.util.StringUtils.hasText(accesstoken)) {

            ResultMessageStruct resultMessageStruct = userCenterServiceClient.logout(accesstoken);

            if (resultMessageStruct.getCode() == 500)
                throw new CustomMessageException(resultMessageStruct.getMessage());
            if (resultMessageStruct.getCode() != 200)
                throw new CustomException(UserExceptionEnum.getEnumByCode(resultMessageStruct.getCode()));
        }
    }

    /**
     * 特地为其它站点添加的登出接口，避免重复
     * @throws Exception
     */
    @PostMapping("logoutBySite")
    public void logoutBySite() throws Exception{
        ServletRequestAttributes servletRequestAttributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String accesstoken = request.getHeader("accessToken");
        if (StringUtils.isEmpty(accesstoken)) {
            // 若header中没有,则从参数中获取
            accesstoken = request.getParameter("accessToken");
        }

        if (org.springframework.util.StringUtils.hasText(accesstoken)) {

            ResultMessageStruct resultMessageStruct = userCenterServiceClient.logoutBySite(accesstoken);

            if (resultMessageStruct.getCode() == 500)
                throw new CustomMessageException(resultMessageStruct.getMessage());
            if (resultMessageStruct.getCode() != 200)
                throw new CustomException(UserExceptionEnum.getEnumByCode(resultMessageStruct.getCode()));
        }
    }

    /**
     * 接口两用：1.用于忘记密码，需要传登录用户名，新密码
     *           2.用户修改老密码，需要旧密码和新密码，登录用户名通过token自主获取
     * @param sysUser
     * @param oldPassword
     * @param request
     * @throws Exception
     */
    @PostMapping("updatePassword")
    public void updatePassword(@ModelAttribute SysUser sysUser, String oldPassword, HttpServletRequest request) throws Exception {

        if (StringUtils.isEmpty(sysUser.getEmail()) && StringUtils.isEmpty(sysUser.getPhone())) {
            String accessToken = request.getHeader("accessToken");
            if (StringUtils.isEmpty(accessToken))
                throw new CustomException(UserExceptionEnum.TOKEN_NOT_EXIST);
            Token token = tokenService.validate(accessToken).getData();
            sysUser.setEmail(token.getAccount());
            sysUser.setPhone(token.getAccount());
        }

        UserParameterDataStruct<SysUser, String> userParameterDataStruct = new UserParameterDataStruct<>();
        userParameterDataStruct.setData(sysUser);
        userParameterDataStruct.setCode(oldPassword);

        ResultMessageStruct resultMessageStruct = userCenterServiceClient.userUpdatePassword(userParameterDataStruct);

        if (resultMessageStruct.getCode() == 500)
            throw new CustomMessageException(resultMessageStruct.getMessage());
        if (resultMessageStruct.getCode() != 200)
            throw new CustomException(UserExceptionEnum.getEnumByCode(resultMessageStruct.getCode()));
    }
}
